package com.hsamgle.service;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.alidns.model.v20150109.*;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsResponse.Record;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainsResponse.Domain;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.utils.StringUtils;
import com.hsamgle.constant.Config;
import com.hsamgle.ui.DomainForm;
import com.hsamgle.utils.IpUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @feature: TODO
 * @packge: com.hsamgle.service
 * @author: 黄鹤老板
 * @create_time: 2019/7/6 14:04
 * @company: 江南皮革厂
 */
public class Handler implements Runnable {

    private static DomainForm form;

    @Override
    public void run ( ) {
        syncNow();
    }



     /**
       * 
       * @method:	TODO       执行数据初始化
       * @time  :	2019/7/6 14:05
       * @author:	黄鹤老板
       * @return:
       */
    public static void init(DomainForm form){
        Handler.form = form;
        try( InputStream stream =  Handler.class.getClassLoader().getResourceAsStream("hosts")){

            form.appendLog("正在初始化数据…………");

            byte[] bytes = new byte[stream.available()];
            int read = stream.read(bytes);


            String pIp = IpUtils.getPublicIp();
            String lIp = IpUtils.getLocalIp();
            String lastTimePIP = "";
            String status = "尚未做解析";
            String lastTime = "尚未执行过同步";
            String domain = "";


            if(read>0){
                String hosts = new String(bytes);
                String[] hostsInfo = hosts.split("#");
                if(hostsInfo.length==3){
                    lastTimePIP = hostsInfo[0];
                    domain = hostsInfo[1];
                    lastTime = hostsInfo[2];
                }
            }

            form.setDomain(domain);
            form.setLastTimePublicIp(lastTimePIP);
            form.setStatus(status);
            form.setPublicIpValue(pIp);
            form.setLocalIpValue(lIp);
            form.setLastTimeSync(lastTime);

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    
     /**
       * 
       * @method:	TODO       执行初始化
       * @time  :	2019/7/6 15:38
       * @author:	黄鹤老板
       * @return:
       */
    public static void syncNow(){
        try {
            String targetDomain = form.getDomain();
            if( StringUtils.isEmpty(targetDomain)){
                return;
            }

            String hostName = targetDomain.substring(targetDomain.indexOf(".")+1);
            String rr = targetDomain.substring(0,targetDomain.indexOf("."));

            IClientProfile profile = DefaultProfile.getProfile(Config.REGION_ID, Config.A_KEY, Config.S_KEY);
            IAcsClient client = new DefaultAcsClient(profile);

            Record dnsRecord = null;

            // 检查当前域名和对应的解释是否发生过更改
            List<Record> records = getDescribeRecords(client, hostName);
            if(!records.isEmpty()){
                form.appendLog("正在校验域名解析列表:");
                for ( Record record : records ) {
                    String recordInfo = record.getRR() + "." + record.getDomainName();
                    form.appendLog("   "+recordInfo);
                    if(targetDomain.equals(recordInfo)){
                        form.appendLog("   已经匹配到相关记录");
                        dnsRecord = record;
                        break;
                    }
                }
            }

            if(dnsRecord!=null){
                // 证明当前解析记录已经存在，这个时候需要分析当前的ip 跟上述的ip 是否一致
                if(form.getPublicIp().equals(dnsRecord.getValue())){
                    // ip 一致，证明不需要进行再次更新记录
                    form.appendLog("记录校验一致，不需要执行更新操作！");
                    form.setStatus("解析已同步成功！！");
                    return;
                }
                // 公网 ip 发生过更改，需要进行更新解析记录
                updateDomainRecord(client, form.getPublicIp(), rr, dnsRecord.getRecordId());
                form.appendLog("解析记录已更新,解析地址已更新为:  "+dnsRecord.getValue()+"  ->  "+form.getPublicIp());
                return;
            }

            // 如果 dnsRecord 为空的话，证明当前需要解析的记录尚不存在，需要进行添加

            // 在添加之前，需要进行校验指定的域名是否存在
            List<Domain> domains = getDomains(client);
            boolean checkDomain = false;
            for ( Domain domain : domains ) {
                if(hostName.equals(domain.getDomainName())){
                    checkDomain = true;
                    break;
                }
            }

            if(checkDomain){
                // 检查域名通过，可以执行添加域名操作
                addHostRecord(client);
                form.appendLog("新增解析记录：  "+form.getDomain()+"  ->  "+form.getPublicIp());
                updateHosts();
            }else {
                // 当前执行的域名不存在，不能完成相关操作
                form.appendLog("新增域名失败! 因为 "+hostName + "域名不存在");
                form.setStatus("解析同步失败！！！！");
            }
        }catch (Exception e){
            e.printStackTrace();
            form.appendLog("解析同步失败！！！！ 因为: \n    "+e.getMessage());
            form.setStatus("解析同步失败！！！！");
        }
    }

     /**
       *
       * @method:	TODO    获取账户下域名列表
       * @time  :	2019/7/6 16:55
       * @author:	黄鹤老板
       * @return:
       */
    private static List<Domain> getDomains(IAcsClient client) throws ClientException {
        form.appendLog("正在加载域名列表！");
        DescribeDomainsRequest request = new DescribeDomainsRequest();
        DescribeDomainsResponse response  = client.getAcsResponse(request);
        return response.getDomains();
    }


     /**
       * 
       * @method:	TODO    添加记录
       *      Action	String	是	操作接口名，系统规定参数，取值：AddDomainRecord
       *      DomainName	String	是	域名名称
       *      RR	String	是	主机记录，如果要解析@.exmaple.com，主机记录要填写”@”，而不是空
       *      Type	String	是	解析记录类型，参见解析记录类型格式
       *      Value	String	是	记录值
       *      TTL	Long	否	解析生效时间，默认为600秒（10分钟），参见TTL定义说明
       *      Priority	Long	否	MX记录的优先级，取值范围[1,10]，记录类型为MX记录时，此参数必须
       *      Line	String	否	解析线路，默认为default。参见解析线路枚举
       * @time  :	2019/7/6 16:55
       * @author:	黄鹤老板
       * @return:
       */
    private static AddDomainRecordResponse addHostRecord(IAcsClient client) throws Exception{
        form.appendLog("正在添加域名解析记录！");
        AddDomainRecordRequest request = new AddDomainRecordRequest();
        String domain = form.getDomain();
        String hostName = domain.substring(domain.indexOf(".")+1);
        String rr = domain.substring(0,domain.indexOf("."));
        request.setValue(form.getPublicIp());
        request.setDomainName(hostName);
        request.setType("A");
        request.setRR(rr);
        return client.getAcsResponse(request);
    }

     /**
       *
       * @method:	TODO    获取域名解释记录列表
       * @time  :	2019/7/6 16:57
       * @author:	黄鹤老板
       * @return:
       */
    private static List<Record> getDescribeRecords(IAcsClient client,String hostName) throws ClientException {
        form.appendLog("正在加载域名解析列表！");
        DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();
        request.setDomainName(hostName);
        DescribeDomainRecordsResponse response = client.getAcsResponse(request);
        return response.getDomainRecords();
    }

     /**
       *
       * @method:	TODO    更新域名解释
       * @time  :	2019/7/6 22:39
       * @author:	黄鹤老板
       * @return:
       */
    private static UpdateDomainRecordResponse updateDomainRecord(IAcsClient client,String value,String rr,String recordId) throws ClientException {
        form.appendLog("正在更新域名解析记录！");
        UpdateDomainRecordRequest update = new UpdateDomainRecordRequest();
        update.setValue(value);
        update.setType("A");
        update.setRR(rr);
        update.setRecordId(recordId);
        return client.getAcsResponse(update);
    }

     /**
       * 
       * @method:	TODO       更新本地hosts记录
       * @time  :	2019/7/6 23:03
       * @author:	黄鹤老板
       * @return:
       */
    private static void updateHosts(){

        String hosts = Handler.class.getClassLoader().getResource("hosts").getPath();
        form.setStatus("解析已同步成功！！");
        try ( FileWriter writer = new FileWriter(new File(hosts)) ) {
            LocalDateTime ldt = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String now = formatter.format(ldt);
            String record = form.getPublicIp()+"#"+form.getDomain()+"#"+now;
            writer.write(record);
            writer.flush();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


}
